home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / C and C++ / GIF source / GIFstuff⁄gifencod.c < prev   
Text File  |  1989-05-25  |  6KB  |  280 lines

  1.  
  2. /*****************************************************************************
  3.  *
  4.  * GIFENCODE.C    - GIF Image compression interface
  5.  *
  6.  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background,
  7.  *            BitsPerPixel, Red, Green, Blue, GetPixel )
  8.  *
  9.  *****************************************************************************/
  10.  
  11. #include <stdio.h>
  12.  
  13. /*
  14.  * Pointer to function returning an int
  15.  */
  16. typedef int (* ifunptr)();
  17.  
  18. #define TRUE 1
  19. #define FALSE 0
  20.  
  21. static int Width, Height;
  22. static int curx, cury;
  23. static long CountDown;
  24. static int Pass = 0;
  25. static int Interlace;
  26.  
  27. /*
  28.  * Bump the 'curx' and 'cury' to point to the next pixel
  29.  */
  30. static
  31. BumpPixel()
  32. {
  33.         /*
  34.          * Bump the current X position
  35.          */
  36.         curx++;
  37.  
  38.         /*
  39.          * If we are at the end of a scan line, set curx back to the beginning
  40.          * If we are interlaced, bump the cury to the appropriate spot,
  41.          * otherwise, just increment it.
  42.          */
  43.         if( curx == Width ) {
  44.                 curx = 0;
  45.  
  46.                 if( !Interlace )
  47.                         cury++;
  48.                 else {
  49.                      switch( Pass ) {
  50.  
  51.                        case 0:
  52.                           cury += 8;
  53.                           if( cury >= Height ) {
  54.                                 Pass++;
  55.                                 cury = 4;
  56.                           }
  57.                           break;
  58.  
  59.                        case 1:
  60.                           cury += 8;
  61.                           if( cury >= Height ) {
  62.                                 Pass++;
  63.                                 cury = 2;
  64.                           }
  65.                           break;
  66.  
  67.                        case 2:
  68.                           cury += 4;
  69.                           if( cury >= Height ) {
  70.                              Pass++;
  71.                              cury = 1;
  72.                           }
  73.                           break;
  74.  
  75.                        case 3:
  76.                           cury += 2;
  77.                           break;
  78.                         }
  79.                 }
  80.         }
  81. }
  82.  
  83. /*
  84.  * Return the next pixel from the image
  85.  */
  86. GIFNextPixel( getpixel )
  87. ifunptr getpixel;
  88. {
  89.         int r;
  90.  
  91.         if( CountDown == 0 )
  92.                 return EOF;
  93.  
  94.         CountDown--;
  95.  
  96.         r = ( * getpixel )( curx, cury );
  97.  
  98.         BumpPixel();
  99.  
  100.         return r;
  101. }
  102.  
  103. /* public */
  104.  
  105. GIFEncode( FName, GWidth, GHeight, GInterlace, Background,
  106.            BitsPerPixel, Red, Green, Blue, GetPixel )
  107.  
  108. char *FName;
  109. int GWidth, GHeight;
  110. int GInterlace;
  111. int Background;
  112. int BitsPerPixel;
  113. int Red[], Green[], Blue[];
  114. ifunptr GetPixel;
  115.  
  116. {
  117.         FILE *fp;
  118.         int B;
  119.         int RWidth, RHeight;
  120.         int LeftOfs, TopOfs;
  121.         int Resolution;
  122.         int ColorMapSize;
  123.         int InitCodeSize;
  124.         int i;
  125.  
  126.         Interlace = GInterlace;
  127.  
  128.         ColorMapSize = 1 << BitsPerPixel;
  129.  
  130.         RWidth = Width = GWidth;
  131.         RHeight = Height = GHeight;
  132.         LeftOfs = TopOfs = 0;
  133.  
  134.         Resolution = BitsPerPixel;
  135.  
  136.         /*
  137.          * Calculate number of bits we are expecting
  138.          */
  139.         CountDown = (long)Width * (long)Height;
  140.  
  141.         /*
  142.          * Indicate which pass we are on (if interlace)
  143.          */
  144.         Pass = 0;
  145.  
  146.         /*
  147.          * The initial code size
  148.          */
  149.         if( BitsPerPixel <= 1 )
  150.                 InitCodeSize = 2;
  151.         else
  152.                 InitCodeSize = BitsPerPixel;
  153.  
  154.         /*
  155.          * Set up the current x and y position
  156.          */
  157.         curx = cury = 0;
  158.  
  159.         /*
  160.          * Open the GIF file for binary write
  161.          */
  162.         fp = fopen( FName, "wb" );
  163.  
  164.         if( fp == (FILE *)0 ) {
  165.                 printf( "error: could not open output file\n" );
  166.                 exit(1);
  167.         }
  168.  
  169.         /*
  170.          * Write the Magic header
  171.          */
  172.         fwrite( "GIF87a", 1, 6, fp );
  173.  
  174.         /*
  175.          * Write out the screen width and height
  176.          */
  177.         Putword( RWidth, fp );
  178.         Putword( RHeight, fp );
  179.  
  180.         /*
  181.          * Indicate that there is a global colour map
  182.          */
  183.         B = 0x80;       /* Yes, there is a color map */
  184.  
  185.         /*
  186.          * OR in the resolution
  187.          */
  188.         B |= (Resolution - 1) << 5;
  189.  
  190.         /*
  191.          * OR in the Bits per Pixel
  192.          */
  193.         B |= (BitsPerPixel - 1);
  194.  
  195.         /*
  196.          * Write it out
  197.          */
  198.         fputc( B, fp );
  199.  
  200.         /*
  201.          * Write out the Background colour
  202.          */
  203.         fputc( Background, fp );
  204.  
  205.         /*
  206.          * Byte of 0's (future expansion)
  207.          */
  208.         fputc( 0, fp );
  209.  
  210.         /*
  211.          * Write out the Global Colour Map
  212.          */
  213.         for( i=0; i<ColorMapSize; i++ ) {
  214.                 fputc( Red[i], fp );
  215.                 fputc( Green[i], fp );
  216.                 fputc( Blue[i], fp );
  217.         }
  218.  
  219.         /*
  220.          * Write an Image separator
  221.          */
  222.         fputc( ',', fp );
  223.  
  224.         /*
  225.          * Write the Image header
  226.          */
  227.  
  228.         Putword( LeftOfs, fp );
  229.         Putword( TopOfs, fp );
  230.         Putword( Width, fp );
  231.         Putword( Height, fp );
  232.  
  233.         /*
  234.          * Write out whether or not the image is interlaced
  235.          */
  236.         if( Interlace )
  237.                 fputc( 0x40, fp );
  238.         else
  239.                 fputc( 0x00, fp );
  240.  
  241.         /*
  242.          * Write out the initial code size
  243.          */
  244.         fputc( InitCodeSize, fp );
  245.  
  246.         /*
  247.          * Go and actually compress the data
  248.          */
  249.         compress( InitCodeSize+1, fp, GetPixel );
  250.  
  251.         /*
  252.          * Write out a Zero-length packet (to end the series)
  253.          */
  254.         fputc( 0, fp );
  255.  
  256.         /*
  257.          * Write the GIF file terminator
  258.          */
  259.         fputc( ';', fp );
  260.  
  261.         /*
  262.          * And close the file
  263.          */
  264.         fclose( fp );
  265.  
  266. }
  267.  
  268. /*
  269.  * Write out a word to the GIF file
  270.  */
  271. static
  272. Putword( w, fp )
  273. int w;
  274. FILE *fp;
  275. {
  276.         fputc( w & 0xff, fp );
  277.         fputc( (w / 256) & 0xff, fp );
  278. }
  279.  
  280.